#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/workqueue.h>
#include <linux/delay.h>

int irq;
struct work_struct test_workqueue;
struct workqueue_struct *myworkqueue;

//中断下半部
void test_work(struct work_struct *work) {
    printk("test_work\n");
    msleep(1000);
    printk("test_work end\n");
}

//中断上半部
irqreturn_t test_interrupt(int irq, void* str) {
    printk("test_interrupt\n");
    
    //工作队列调度
    queue_work(myworkqueue, &test_workqueue);
    return IRQ_RETVAL(IRQ_HANDLED); // 中断已经发生
}


int __init define_queue_init(void) {
    int ret = 0;
    printk("define_queue_init\n");
    
    //将gpio映射为中断号
    irq = gpio_to_irq(42);
    printk("irq is %d\n", irq);

    //请求中断
    ret = request_irq(irq, test_interrupt, IRQF_TRIGGER_RISING, "test", NULL);
    if (ret < 0) {
        printk("request_irq failed\n");
        return -1;
    }

    //创建自定义工作队列
    myworkqueue = alloc_workqueue("Concurrency_queue", WQ_UNBOUND, 0);
    if (!myworkqueue) {
        printk("create_workqueue failed\n");
        return -1;
    }
    
    //初始化工作项
    INIT_WORK(&test_workqueue, test_work);

    return 0;
}

void  __exit define_queue_exit(void) {
    //释放中断
    free_irq(irq, NULL);
    //取消工作队列
    cancel_work_sync(&test_workqueue);
    //刷新工作队列
    flush_workqueue(myworkqueue);
    //销毁工作队列
    destroy_workqueue(myworkqueue);

    printk("define_queue_exit\n");
}

module_init(define_queue_init);
module_exit(define_queue_exit);
MODULE_LICENSE("GPL");